from flask import Flask, render_template, request, redirect,url_for
from flask_mail import Mail, Message
import random
from flask_sqlalchemy import SQLAlchemy
import re
import datetime
from sqlalchemy import or_
from flask_cors import CORS # 跨域

# 发送邮箱设置不用更改
from config import *
app = Flask(__name__)
app.config['MAIL_SERVER']='smtp.qq.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = '1131659949@qq.com'
app.config['MAIL_PASSWORD'] = 'rggctcttjgrojjba'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail = Mail(app)
app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
db = SQLAlchemy(app)

# CORS(app)
CORS(app, resources={r"/*": {"origins": "http://localhost:8000", "supports_credentials": True}}) 

# 用户
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True)
    password = db.Column(db.String(20), unique=False)
    email = db.Column(db.String(120), unique=True)

    def __init__(self, username, email, password):
        self.username = username
        self.email = email
        self.password = password

    def __repr__(self):
        return '<User %r>' % self.username

# 验证码
class VerificationCode(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    code = db.Column(db.Integer, unique=False)
    expiration = db.Column(db.DateTime)

    def __init__(self, code, expiration):
        self.code = code
        self.expiration = expiration


@app.route("/user/registered" ,methods = ['POST', 'GET'])
def register():
    if request.method == "POST":
        data = request.form
        requires_fields = ["username", "password", "email", "code"]

        for i in requires_fields:
            if not data.get(i, None):
                return {"err": "请填写完整表单"}, 200

        username_pattern = r"^[A-Za-z0-9_-]{4,16}$"
        password_pattern = r"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{4,16}$"

        if not re.match(username_pattern, data["username"]):

            return {"err": "用户名必须为4-16位由数字，字母，减号，下划线组成"}, 200

        if not re.match(password_pattern, data["password"]):
            return {"err": "密码必须包含一个大写字母，一个小写字母和一个数字"}, 200

        rex = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"
        if not re.match(rex, data["email"]):
            return {"err": "邮箱格式错误"}, 200

        _code = VerificationCode.query.filter_by(code=data["code"]).first()
        if _code is None or _code.expiration < datetime.datetime.now():
            if _code:
                db.session.delete(_code)
                db.session.commit()
            return {"err": "验证码无效"}, 200

        try:
            db.session.delete(_code)
            if User.query.filter(or_(User.username==data["username"], User.email==data["email"])).first():
                return {"err": "已存在相同用户名或者邮箱"}
            user = User(username=data["username"], email=data["email"], password=data["password"])
            db.session.add(user)
            db.session.commit()
        except Exception as e:
            return {"err": "已存在相同用户名或者邮箱"}


        return {"msg": "注册成功"}, 200
    return redirect('/login')

@app.route('/login',methods = ['POST', 'GET'])
def login():  # put application's code here
    if request.method == 'GET':
        return render_template('login.html')
    else:
        data = request.form
        user = User.query.filter_by(**data).first()
        if not user:
            return {"err": "用户名或密码错误"}, 200
        return {"msg": "登录成功"}, 200

@app.route("/test",methods = ['GET'])
def test():
    return render_template('test.html')
@app.route("/email",methods = ['POST', 'GET'])
def emailAPI():
    data = request.form
    rex = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"
    email = data.get("email")
    if not re.match(rex, email):
        return {"err": "邮箱格式错误"}
    return {"msg": send_mail(email)}


def send_mail(to):
    try:
        code = str(random_number())
        msg = Message(subject="验证码", sender=app.config.get("MAIL_USERNAME"), recipients=[to], html=f"<div>您的验证码为<span style='font-weight: blod'>{code}</span>,该验证码五分钟内有效</div>")
        mail.send(msg)
        db_row = VerificationCode(code=code, expiration=datetime.datetime.now() + datetime.timedelta(minutes=5))
        db.session.add(db_row)
        db.session.commit()
        return True
    except Exception as e:
        return False


# 验证码随机
def random_number():
    return random.randint(100000, 999999)

if __name__ == '__main__':
    app.run(port=5000)
